﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Common.Utilities.TextMatch;

namespace DiscoveryLogic.Analytics.Modules.Clusters
{
    /// <summary>
    /// Interaction logic for TagCloud.xaml
    /// </summary>
    public partial class TagCloud : UserControl
    {
        private static ListCollectionView lcv;
        private TagCloudPresenter _Presenter;

        #region dependency properties

        public static readonly DependencyProperty TagsCollectionProperty =
            DependencyProperty.Register("TagsCollection", typeof(Object), typeof(TagCloud),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(TagsCollectionProperty_Changed)));

        /// <summary>
        /// The Collection that will be used to build the Tag Cloud
        /// </summary>
        public Object TagsCollection
        {
            get { return (Object)GetValue(TagsCollectionProperty); }
            set { SetValue(TagsCollectionProperty, value); }
        }

        public static readonly DependencyProperty SortDescriptorProperty =
            DependencyProperty.Register("SortDescriptor", typeof(string), typeof(TagCloud));

        /// <summary>
        /// The SortDescriptor is used for sorting the TagsCollection
        /// </summary>
        public string SortDescriptor
        {
            get { return (string)GetValue(SortDescriptorProperty); }
            set { SetValue(SortDescriptorProperty, value); }
        }

        public static readonly DependencyProperty GroupDescriptorProperty =
            DependencyProperty.Register("GroupDescriptor", typeof(string), typeof(TagCloud));

        /// <summary>
        /// The GroupDescriptor is usef for goruping the collection into tags
        /// </summary>
        public string GroupDescriptor
        {
            get { return (string)GetValue(GroupDescriptorProperty); }
            set { SetValue(GroupDescriptorProperty, value); }
        }

        #endregion

        #region routed events

        public delegate void OnTagSelectionChanged(TermWeight tw);
        public event OnTagSelectionChanged TagSelectionChanged;

        #endregion

        public TagCloud()
        {
            InitializeComponent();
        }

        public TagCloud(TagCloudPresenter presenter):this()
        {
            this._Presenter = presenter;
            this._Presenter.View = this;
        }

        /// <summary>
        /// Used as a filter predicate to see if the person should be included 
        /// </summary>
        /// <param name="o">Person object</param>
        /// <returns>True if the person should be included in the filter, otherwise false</returns>
        public static bool FilterItem(object o)
        {
            TermWeight termUsage =(TermWeight) o;
            if (string.IsNullOrEmpty(termUsage.Term) || termUsage.Weight == 0)
                return false;
            if (string.IsNullOrEmpty(termUsage.Term))
                return false;
            else
            {
                return true;
            }
        }

        private static void TagsCollectionProperty_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            // ListCollectionView is used for sorting and grouping
            lcv = new ListCollectionView((IList)args.NewValue);

            TagCloud tagCloud = ((TagCloud)sender);

            // Apply sorting
            if (!string.IsNullOrEmpty(tagCloud.SortDescriptor))
                lcv.SortDescriptions.Add(new SortDescription(tagCloud.SortDescriptor, ListSortDirection.Ascending));

            // Group the collection into tags. The tag cloud will be based on the group Name and ItemCount
            lcv.GroupDescriptions.Add(new PropertyGroupDescription(tagCloud.GroupDescriptor));

            // Exclude people without lastnames
            lcv.Filter = new Predicate<object>(FilterItem);

            tagCloud.TagCloudListBox.ItemsSource = lcv.Groups;
        }

        //private void TagCloudListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        //{
        //    CollectionViewGroup selected = (CollectionViewGroup)((ListBox)sender).SelectedItem;

        //    if (selected != null)
        //        RaiseEvent(new RoutedEventArgs(TagSelectionChangedEvent, selected.Name));
        //}

        internal static void Refresh()
        {
            lcv.Refresh();
        }

        internal void ClearSelection()
        {
            TagCloudListBox.UnselectAll();
        }

        public List<TermWeight> TermWeights 
        {
            get { return this.TagCloudListBox.ItemsSource as List<TermWeight>; }
            set
            {
                this.TagCloudListBox.ItemsSource = value;
                if (value == null || value.Count == 0)
                {
                    this.Visibility = System.Windows.Visibility.Collapsed;
                }
                else
                {
                    this.Visibility = System.Windows.Visibility.Visible;
                }
            }
        }

        public void SubscribeEventHandler(TermWeight tw)
        {
            this._Presenter.RegisterTagSelectionChangedEventHandler(tw);
        }

        private void TagCloudListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 1)
            {
                TermWeight tw = e.AddedItems[0] as TermWeight;
                if (this.TagSelectionChanged != null)
                    this.TagSelectionChanged(tw);
            }
        }

        public void SelectTag(TermWeight tw)
        {
            if (this.TermWeights != null && tw != null)
            {
                for (int i = 0; i < this.TermWeights.Count; i++)
                {
                    if (this.TermWeights[i].Term == tw.Term)
                    {
                        this.TagCloudListBox.SelectedIndex = i;
                        break;
                    }
                }
            }
        }
    }
}
